package com.evil.account.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.evil.account.api.RemoteUserRoleService;
import com.evil.account.mapper.RoleMapper;
import com.evil.account.mapper.UserRoleMapper;
import com.evil.account.pojo.entity.Role;
import com.evil.account.pojo.entity.UserRole;
import com.evil.account.service.UserEnterpriseService;
import com.evil.account.service.UserRoleService;
import com.evil.common.account.dto.role.RoleBaseRespDTO;
import com.evil.common.account.dto.user.UserBaseRespDTO;
import com.evil.common.account.dto.user.UserEnterpriseDTO;
import com.evil.common.account.dto.user.role.RoleUsersReqDTO;
import com.evil.common.account.util.LoginUtil;
import com.evil.common.core.dto.FindByIdReqDTO;
import com.evil.common.core.dto.FindByIdsReqDTO;
import com.evil.common.core.enums.RCodeEnum;
import com.evil.common.core.enums.SwitchEnum;
import com.evil.common.core.exception.BusinessException;
import com.evil.common.core.util.StreamUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 角色表
 *
 * @author liyang
 * @date 2022-08-08 00:00
 */
@Slf4j
@Service
@AllArgsConstructor
public class UserRoleServiceImpl extends ServiceImpl<UserRoleMapper, UserRole> implements UserRoleService, RemoteUserRoleService {

    private final LoginUtil loginUtil;

    private final RoleMapper roleMapper;

    private final UserEnterpriseService userEnterpriseService;

    private final AccountLogServiceImpl accountLogService;

    /**
     * 获取企业用户角色列表
     *
     * @param userEnterpriseDTO userEnterpriseDTO
     * @return UserRole 列表
     */
    @Override
    public List<UserRole> findByEnterpriseUser(UserEnterpriseDTO userEnterpriseDTO) {
        return this.baseMapper.findByUserId(userEnterpriseDTO.getEnterpriseId(), userEnterpriseDTO.getUserId(), true);
    }

    /**
     * 用户角色基础信息
     *
     * @param userEnterpriseDTO userEnterpriseDTO
     * @return RoleBaseRespDTO 列表
     */
    @Override
    public List<RoleBaseRespDTO> userRoleBases(UserEnterpriseDTO userEnterpriseDTO) {
        return this.baseMapper.findByUserEnterprise(userEnterpriseDTO);
    }

    /**
     * 修改用户角色（覆盖性）
     *
     * @param enterpriseId enterpriseId
     * @param userId       userId
     * @param roleIds      roleIds
     */
    @Override
    public void modify(Long enterpriseId, Long userId, List<Long> roleIds) {
        List<UserRole> userRoles = this.baseMapper.findByUserId(enterpriseId, userId, false);

        List<UserRole> modifies = new ArrayList<>();

        Set<Long> existRoleIds = new HashSet<>();
        if (CollectionUtil.isNotEmpty(roleIds)) {
            List<Role> roleList = roleMapper.findByIds(roleIds, true);
            if (roleList.size() != roleIds.size()) {
                throw new BusinessException(RCodeEnum.ROLE_NOT_EXIST);
            }
        } else {
            roleIds = new ArrayList<>();
        }

        // 编辑
        for (UserRole ur : userRoles) {
            existRoleIds.add(ur.getRoleId());
            if (roleIds.contains(ur.getRoleId())) {
                // 已存在的--修改为未删除
                ur.setIsDeleted(SwitchEnum.NO.getId());
                modifies.add(ur);
            } else {
                // 未删除，需要删除
                if (SwitchEnum.isOpen(ur.getIsDeleted())) {
                    ur.setIsDeleted(SwitchEnum.YES.getId());
                    modifies.add(ur);
                }
            }
        }
        // 新增
        modifies.addAll(StreamUtil.transListFT(roleIds, r -> !existRoleIds.contains(r), r -> this.createUserRole(enterpriseId, userId, r)));

        accountLogService.saveBatchAndCheck(this.baseMapper, UserRole::getId, modifies);
    }

    /**
     * 获取指定角色 用户id
     *
     * @param findByIdReqDTO findByIdReqDTO
     * @return userIds
     */
    @Override
    public List<Long> findUserIdsByRoleId(FindByIdReqDTO findByIdReqDTO) {
        return this.baseMapper.findUserIdsByRoleId(findByIdReqDTO.getId(), findByIdReqDTO.getFilterDeleted());
    }

    /**
     * 获取指定角色 用户基础信息列表
     *
     * @param findByIdsReqDTO findByIdsReqDTO
     * @return userIds
     */
    @Override
    public List<UserBaseRespDTO> findUserBasesByRoleIds(FindByIdsReqDTO findByIdsReqDTO) {
        return this.baseMapper.findUserBasesByRoleIds(findByIdsReqDTO);
    }

    /**
     * 获取指定角色 用户ids
     *
     * @param findByIdsReqDTO findByIdsReqDTO
     * @return userIds
     */
    @Override
    public List<Long> findUserIdsByRoleIds(FindByIdsReqDTO findByIdsReqDTO) {
        return this.baseMapper.findUserIdsByRoleIds(findByIdsReqDTO);
    }

    /**
     * 角色批量删除用户
     *
     * @param roleUsersReqDTO roleUsersReqDTO
     */
    @Override
    public void deleteUserRoleBatch(RoleUsersReqDTO roleUsersReqDTO) {
        roleUsersReqDTO.setEnterpriseId(loginUtil.getParamEnterpriseId(roleUsersReqDTO.getEnterpriseId()));
        // 检查企业管理员
        userEnterpriseService.checkEnterpriseManager(loginUtil.getLoginUserEnterprise());

        List<Long> userIds = roleUsersReqDTO.getUserIds();

        Role role = roleMapper.findById(roleUsersReqDTO.getRoleId());
        // 检查企业
        loginUtil.checkEnterpriseId(role.getEnterpriseId(), roleUsersReqDTO.getEnterpriseId());

        List<UserRole> userRoles = this.baseMapper.findByRIdAndUIds(role.getRoleId(), userIds, true);
        userRoles.forEach(ur -> ur.setIsDeleted(SwitchEnum.YES.getId()));
        accountLogService.saveBatchAndCheck(this.baseMapper, UserRole::getId, userRoles);
    }

    /**
     * 角色批量新增用户
     *
     * @param roleUsersReqDTO roleUsersReqDTO
     */
    @Override
    public void addUserRoleBatch(RoleUsersReqDTO roleUsersReqDTO) {
        roleUsersReqDTO.setEnterpriseId(loginUtil.getParamEnterpriseId(roleUsersReqDTO.getEnterpriseId()));
        // 检查企业管理员
        userEnterpriseService.checkEnterpriseManager(loginUtil.getLoginUserEnterprise());

        Long roleId = roleUsersReqDTO.getRoleId();
        Long enterpriseId = roleUsersReqDTO.getEnterpriseId();
        Set<Long> userIds = new HashSet<>(roleUsersReqDTO.getUserIds());

        Role role = roleMapper.findById(roleId);
        // 检查企业
        loginUtil.checkEnterpriseId(role.getEnterpriseId(), enterpriseId);

        List<UserRole> userRoles = this.baseMapper.findByRIdAndUIds(role.getRoleId(), userIds, false);
        Map<Long, UserRole> userRoleMap = StreamUtil.toMapK(userRoles, UserRole::getUserId);

        List<UserRole> modifies = new ArrayList<>();
        // 新增/编辑
        userIds.forEach(userId -> {
            if (userRoleMap.containsKey(userId)) {
                // 编辑
                UserRole userRole = userRoleMap.get(userId);
                // 已删除的 -> 未删除
                if (SwitchEnum.isOpen(userRole.getIsDeleted())) {
                    userRole.setIsDeleted(SwitchEnum.NO.getId());
                    modifies.add(userRole);
                }
            } else {
                // 新增
                modifies.add(this.createUserRole(roleUsersReqDTO.getEnterpriseId(), userId, roleId));
            }
        });

        // 删除
        modifies.addAll(StreamUtil.peekF(userRoles, ur -> !userIds.contains(ur.getUserId()), ur -> ur.setIsDeleted(SwitchEnum.YES.getId())));

        accountLogService.saveBatchAndCheck(this.baseMapper, UserRole::getId, modifies);
    }

    private UserRole createUserRole(Long enterpriseId, Long userId, Long roleId) {
        UserRole userRole = new UserRole();
        userRole.setEnterpriseId(enterpriseId);
        userRole.setUserId(userId);
        userRole.setRoleId(roleId);
        userRole.setIsEnable(SwitchEnum.NO.getId());
        userRole.setIsDeleted(SwitchEnum.NO.getId());
        return userRole;
    }
}
